/*
 * @(#)PAVAS.java	1.0 Mar 8, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.ai.pavas;

import java.util.concurrent.ConcurrentHashMap;

/**
 * The original PAVAS design (My 1998 Capstone) listed the Logical-Creative as
 * a State(-50 to +50, 0=balanced), and the rest as Traits(0-100%), because the
 * Logical-Creative measurement was seen to be a situation-specific measurement.
 *
 * I have, however, came to conclude that the conceptual difference between Traits
 * and States is incorrect.  I believe that all Traits/States are situational. An
 * angry person, for example, may have a tendancy to be angry, but that does not
 * mean that he is ALWAYS angry, as would be the assumption from a fixed-Trait.
 *
 * Instead, I take the approach that a Trait is the "default" state. Situations
 * modify these Traits to come up with temporary situational states.  Thus, an
 * "Aggressive-Passive" Trait of 20% might be increased to 80% when near an
 * abuser, but dropped to 5% when near an infant -- but their BASE State is 20%.
 *
 * Thus, we will use the term "Trait" for all of the Attribute pairs, because the
 * situation has not yet been used to modify it.
 *
 * Also, Lawful is not listed as a Trait (as in Dungeons & Dragons) because it is
 * a lawfullness is a state of morality. See Rohlberg "States of Moral Development".
 */
public class PAVAS
{
	private enum singleton
	{
		attributes;
		singleton()
		{
			map = new ConcurrentHashMap<Attribute,Trait>();
			for(Trait trait : Trait.values())
			{
				map.put(trait.getLowAttribute(), trait);
				map.put(trait.getHighAttribute(), trait);
			}
		}
		private ConcurrentHashMap<Attribute, Trait> map;
		public Trait get(Attribute attr){return map.get(attr);}
	}
	
	private ConcurrentHashMap<Trait,Double> values;
	public PAVAS()
	{
		values = new ConcurrentHashMap<Trait,Double>();
		for(Trait trait : Trait.values())
			values.put(trait, trait.balance());
	}

	public double getTrait(Trait trait)
	{
		if(trait == null)
			throw new IllegalArgumentException("Trait can not be null");

		return values.get(trait);
	}

	public double getTrait(Attribute attr)
	{
		if(attr == null)
			throw new IllegalArgumentException("Attribute can not be null");


		Trait trait = singleton.attributes.get(attr);
		if(trait == null)
			throw new IllegalArgumentException("No Trait is attached to the specified Attribute");

		double value = getTrait(trait);
		if(attr == trait.getLowAttribute())
			return value;

		if(attr == trait.getHighAttribute())
			return 1.00-value;

		return 0.0-value;// error but still show result
	}

	public void setTrait(Trait trait, double value)
	{
		if(trait == null)
			throw new IllegalArgumentException("Trait can not be null");

		values.put(trait, value);
	}

	public void setTrait(Attribute attr, double value)
	{
		if(attr == null)
			throw new IllegalArgumentException("Attribute can not be null");

		Trait trait = singleton.attributes.get(attr);
		if(trait == null)
			throw new IllegalArgumentException("No Trait is attached to the specified Attribute");

		if(attr == trait.getLowAttribute())
			setTrait(trait, value);
		else
			setTrait(trait, 100.0-value);
	}

	public double updateTrait(Trait trait, double modification)
	{
		if(trait == null)
			throw new IllegalArgumentException("Trait can not be null");

		double current = getTrait(trait);
		setTrait(trait, (current + modification));
		return getTrait(trait);
	}

	public double updateTrait(Attribute attr, double modification)
	{
		if(attr == null)
			throw new IllegalArgumentException("Attribute can not be null");

		Trait trait = singleton.attributes.get(attr);
		if(trait == null)
			throw new IllegalArgumentException("No Trait is attached to the specified Attribute");

		double current = getTrait(trait);
		if(attr == trait.getLowAttribute())
			setTrait(trait, (current + modification));
		else
			setTrait(trait, (current - modification));

		return getTrait(trait);
	}
}
